using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace StarSkipGame
{
    /// <summary>
    /// 陨石类
    /// </summary>
    public class Asteroid : GameObject
    {
        // 陨石类型枚举
        public enum AsteroidSize
        {
            Small = 0,
            Medium = 1,
            Large = 2
        }
        
        // 陨石速度类型枚举
        public enum AsteroidSpeed
        {
            Slow = 0,
            Medium = 1,
            Fast = 2
        }
        
        // 陨石属性
        public AsteroidSize Size { get; private set; }
        public AsteroidSpeed Speed { get; private set; }
        
        // 陨石颜色
        private readonly Color asteroidColor = Color.Gray;
        private readonly Color outlineColor = Color.DarkGray;
        
        // 旋转角度
        private float rotationAngle = 0;
        private float rotationSpeed;
        
        // 性能优化：缓存形状
        private PointF[] cachedShape;
        private bool shapeNeedsUpdate = true;
        
        // 速度配置
        private static readonly float[] SpeedValues = { 80.0f, 150.0f, 300.0f }; // 慢、中、快
        private static readonly int[] SizeValues = { 20, 35, 50 }; // 小、中、大
        
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="x">初始X坐标</param>
        /// <param name="y">初始Y坐标</param>
        /// <param name="size">陨石大小</param>
        /// <param name="speed">陨石速度</param>
        /// <param name="directionX">X方向速度</param>
        /// <param name="directionY">Y方向速度</param>
        public Asteroid(float x, float y, AsteroidSize size, AsteroidSpeed speed, float directionX, float directionY) 
            : base(x, y, SizeValues[(int)size], SizeValues[(int)size])
        {
            Size = size;
            Speed = speed;
            
            // 设置速度
            float speedValue = SpeedValues[(int)speed];
            VelocityX = directionX * speedValue;
            VelocityY = directionY * speedValue;
            
            // 设置旋转速度
            Random rand = new Random();
            rotationSpeed = (float)(rand.NextDouble() * 2 - 1) * 2.0f; // -2 到 2 度/帧
            
            // 初始化缓存形状
            UpdateCachedShape();
        }
        
        /// <summary>
        /// 更新陨石状态
        /// </summary>
        /// <param name="deltaTime">时间间隔</param>
        public override void Update(float deltaTime)
        {
            if (!IsActive) return;
            
            // 更新旋转角度
            rotationAngle += rotationSpeed * deltaTime * 60; // 转换为帧率
            if (rotationAngle > 360) rotationAngle -= 360;
            if (rotationAngle < 0) rotationAngle += 360;
            
            // 调用基类更新方法
            base.Update(deltaTime);
            
            // 标记形状需要更新
            shapeNeedsUpdate = true;
        }
        
        /// <summary>
        /// 绘制陨石（优化版本）
        /// </summary>
        /// <param name="g">绘图对象</param>
        public override void Draw(Graphics g)
        {
            if (!IsActive) return;
            
            // 更新缓存的形状
            if (shapeNeedsUpdate)
            {
                UpdateCachedShape();
            }
            
            // 应用旋转变换
            Matrix originalMatrix = g.Transform;
            float centerX = X + Width / 2.0f;
            float centerY = Y + Height / 2.0f;
            
            g.TranslateTransform(centerX, centerY);
            g.RotateTransform(rotationAngle);
            g.TranslateTransform(-centerX, -centerY);
            
            // 绘制陨石主体（使用缓存的形状）
            using (SolidBrush asteroidBrush = new SolidBrush(asteroidColor))
            {
                g.FillPolygon(asteroidBrush, cachedShape);
            }
            
            // 绘制陨石轮廓
            using (Pen asteroidPen = new Pen(outlineColor, 2))
            {
                g.DrawPolygon(asteroidPen, cachedShape);
            }
            
            // 恢复原始变换状态
            g.Transform = originalMatrix;
        }
        
        /// <summary>
        /// 批量绘制陨石（性能优化）
        /// </summary>
        /// <param name="g">绘图对象</param>
        /// <param name="asteroids">要绘制的陨石列表</param>
        public static void DrawBatch(Graphics g, List<Asteroid> asteroids)
        {
            if (asteroids == null || asteroids.Count == 0) return;
            
            // 设置一次绘图质量
            g.SmoothingMode = SmoothingMode.AntiAlias;
            
            // 准备画笔和画刷（重用）
            using (SolidBrush asteroidBrush = new SolidBrush(Color.Gray))
            using (Pen asteroidPen = new Pen(Color.DarkGray, 2))
            {
                foreach (Asteroid asteroid in asteroids)
                {
                    if (!asteroid.IsActive) continue;
                    
                    // 更新缓存的形状
                    if (asteroid.shapeNeedsUpdate)
                    {
                        asteroid.UpdateCachedShape();
                    }
                    
                    // 应用旋转变换
                    Matrix originalMatrix = g.Transform;
                    float centerX = asteroid.X + asteroid.Width / 2.0f;
                    float centerY = asteroid.Y + asteroid.Height / 2.0f;
                    
                    g.TranslateTransform(centerX, centerY);
                    g.RotateTransform(asteroid.rotationAngle);
                    g.TranslateTransform(-centerX, -centerY);
                    
                    // 绘制陨石
                    g.FillPolygon(asteroidBrush, asteroid.cachedShape);
                    g.DrawPolygon(asteroidPen, asteroid.cachedShape);
                    
                    // 恢复变换
                    g.Transform = originalMatrix;
                }
            }
        }
        
        /// <summary>
        /// 更新缓存的形状
        /// </summary>
        private void UpdateCachedShape()
        {
            float centerX = X + Width / 2.0f;
            float centerY = Y + Height / 2.0f;
            float radius = Width / 2.0f;
            
            // 生成8个顶点的不规则多边形
            PointF[] points = new PointF[8];
            Random rand = new Random((int)(X + Y)); // 使用位置作为种子
            
            for (int i = 0; i < 8; i++)
            {
                float angle = (float)(i * Math.PI * 2 / 8);
                float randomRadius = radius * (0.7f + (float)rand.NextDouble() * 0.6f); // 0.7-1.3倍半径
                
                points[i] = new PointF(
                    centerX + (float)Math.Cos(angle) * randomRadius,
                    centerY + (float)Math.Sin(angle) * randomRadius
                );
            }
            
            cachedShape = points;
            shapeNeedsUpdate = false;
        }
        
        /// <summary>
        /// 检查陨石是否移出屏幕
        /// </summary>
        /// <param name="screenWidth">屏幕宽度</param>
        /// <param name="screenHeight">屏幕高度</param>
        /// <returns>是否移出屏幕</returns>
        public bool IsOutOfBounds(int screenWidth, int screenHeight)
        {
            return X + Width < 0 || X > screenWidth || Y + Height < 0 || Y > screenHeight;
        }
        
        /// <summary>
        /// 检查陨石是否在屏幕范围内（用于视锥剔除）
        /// </summary>
        /// <param name="screenWidth">屏幕宽度</param>
        /// <param name="screenHeight">屏幕高度</param>
        /// <returns>是否在屏幕范围内</returns>
        public bool IsVisible(int screenWidth, int screenHeight)
        {
            // 添加一些边距以确保旋转时不会突然消失
            float margin = Width;
            return X + Width + margin >= 0 && X - margin <= screenWidth && 
                   Y + Height + margin >= 0 && Y - margin <= screenHeight;
        }
        
        /// <summary>
        /// 创建随机陨石
        /// </summary>
        /// <param name="screenWidth">屏幕宽度</param>
        /// <param name="screenHeight">屏幕高度</param>
        /// <param name="difficulty">难度系数（0-1）</param>
        /// <param name="seed">随机种子（可选）</param>
        /// <returns>新创建的陨石</returns>
        public static Asteroid CreateRandomAsteroid(int screenWidth, int screenHeight, float difficulty, int? seed = null)
        {
            Random rand = seed.HasValue ? new Random(seed.Value) : new Random();
            
            // 根据难度调整大小和速度分布
            AsteroidSize size;
            AsteroidSpeed speed;
            
            if (difficulty < 0.3f)
            {
                // 初期：主要是小陨石，慢速
                size = rand.NextDouble() < 0.7 ? AsteroidSize.Small : AsteroidSize.Medium;
                speed = rand.NextDouble() < 0.8 ? AsteroidSpeed.Slow : AsteroidSpeed.Medium;
            }
            else if (difficulty < 0.6f)
            {
                // 中期：中等大小和速度
                size = (AsteroidSize)rand.Next(0, 3);
                speed = (AsteroidSpeed)rand.Next(0, 3);
            }
            else
            {
                // 后期：更多大陨石和快速陨石
                size = rand.NextDouble() < 0.4 ? AsteroidSize.Large : (AsteroidSize)rand.Next(0, 3);
                speed = rand.NextDouble() < 0.6 ? AsteroidSpeed.Fast : (AsteroidSpeed)rand.Next(0, 3);
            }
            
            // 随机选择生成位置（屏幕边缘或角落）
            float x, y, directionX, directionY;
            
            int spawnType = rand.Next(8); // 0-3: 四边, 4-7: 四角
            int sizeValue = SizeValues[(int)size];
            
            if (spawnType < 4)
            {
                // 从四边生成
                switch (spawnType)
                {
                    case 0: // 上边缘
                        x = rand.Next(-sizeValue, screenWidth + sizeValue);
                        y = -sizeValue;
                        directionX = (float)(rand.NextDouble() * 2 - 1); // -1 到 1
                        directionY = 1.0f; // 向下
                        break;
                        
                    case 1: // 右边缘
                        x = screenWidth + sizeValue;
                        y = rand.Next(-sizeValue, screenHeight + sizeValue);
                        directionX = -1.0f; // 向左
                        directionY = (float)(rand.NextDouble() * 2 - 1); // -1 到 1
                        break;
                        
                    case 2: // 下边缘
                        x = rand.Next(-sizeValue, screenWidth + sizeValue);
                        y = screenHeight + sizeValue;
                        directionX = (float)(rand.NextDouble() * 2 - 1); // -1 到 1
                        directionY = -1.0f; // 向上
                        break;
                        
                    default: // 左边缘
                        x = -sizeValue;
                        y = rand.Next(-sizeValue, screenHeight + sizeValue);
                        directionX = 1.0f; // 向右
                        directionY = (float)(rand.NextDouble() * 2 - 1); // -1 到 1
                        break;
                }
            }
            else
            {
                // 从四角生成
                switch (spawnType)
                {
                    case 4: // 左上角
                        x = -sizeValue;
                        y = -sizeValue;
                        directionX = (float)(0.5 + rand.NextDouble() * 0.5); // 0.5 到 1.0
                        directionY = (float)(0.5 + rand.NextDouble() * 0.5); // 0.5 到 1.0
                        break;
                        
                    case 5: // 右上角
                        x = screenWidth + sizeValue;
                        y = -sizeValue;
                        directionX = (float)(-1.0 - rand.NextDouble() * 0.5); // -1.5 到 -1.0
                        directionY = (float)(0.5 + rand.NextDouble() * 0.5); // 0.5 到 1.0
                        break;
                        
                    case 6: // 右下角
                        x = screenWidth + sizeValue;
                        y = screenHeight + sizeValue;
                        directionX = (float)(-1.0 - rand.NextDouble() * 0.5); // -1.5 到 -1.0
                        directionY = (float)(-1.0 - rand.NextDouble() * 0.5); // -1.5 到 -1.0
                        break;
                        
                    default: // 左下角
                        x = -sizeValue;
                        y = screenHeight + sizeValue;
                        directionX = (float)(0.5 + rand.NextDouble() * 0.5); // 0.5 到 1.0
                        directionY = (float)(-1.0 - rand.NextDouble() * 0.5); // -1.5 到 -1.0
                        break;
                }
            }
            
            // 标准化方向向量
            float length = (float)Math.Sqrt(directionX * directionX + directionY * directionY);
            directionX /= length;
            directionY /= length;
            
            return new Asteroid(x, y, size, speed, directionX, directionY);
        }
        
        /// <summary>
        /// 初始化陨石对象（用于对象池）
        /// </summary>
        /// <param name="asteroid">要初始化的陨石对象</param>
        /// <param name="screenWidth">屏幕宽度</param>
        /// <param name="screenHeight">屏幕高度</param>
        /// <param name="difficulty">难度系数（0-1）</param>
        public static void InitializeAsteroid(Asteroid asteroid, int screenWidth, int screenHeight, float difficulty)
        {
            // 使用CreateRandomAsteroid的逻辑来初始化现有对象
            Random rand = new Random();
            
            // 根据难度调整大小和速度分布
            AsteroidSize size;
            AsteroidSpeed speed;
            
            if (difficulty < 0.3f)
            {
                size = AsteroidSize.Small;
                speed = AsteroidSpeed.Slow;
            }
            else if (difficulty < 0.7f)
            {
                size = AsteroidSize.Medium;
                speed = AsteroidSpeed.Medium;
            }
            else
            {
                size = AsteroidSize.Large;
                speed = AsteroidSpeed.Fast;
            }
            
            // 随机选择生成位置和方向
            int spawnType = rand.Next(8); // 8个方向
            int sizeValue = SizeValues[(int)size];
            float x, y, directionX, directionY;
            
            // 从边缘生成
            if (spawnType < 4)
            {
                switch (spawnType)
                {
                    case 0: // 上边缘
                        x = rand.Next(-sizeValue, screenWidth + sizeValue);
                        y = -sizeValue;
                        directionX = (float)(rand.NextDouble() * 2 - 1);
                        directionY = 1.0f;
                        break;
                    case 1: // 右边缘
                        x = screenWidth + sizeValue;
                        y = rand.Next(-sizeValue, screenHeight + sizeValue);
                        directionX = -1.0f;
                        directionY = (float)(rand.NextDouble() * 2 - 1);
                        break;
                    case 2: // 下边缘
                        x = rand.Next(-sizeValue, screenWidth + sizeValue);
                        y = screenHeight + sizeValue;
                        directionX = (float)(rand.NextDouble() * 2 - 1);
                        directionY = -1.0f;
                        break;
                    default: // 左边缘
                        x = -sizeValue;
                        y = rand.Next(-sizeValue, screenHeight + sizeValue);
                        directionX = 1.0f;
                        directionY = (float)(rand.NextDouble() * 2 - 1);
                        break;
                }
            }
            else
            {
                // 从四角生成
                switch (spawnType)
                {
                    case 4: // 左上角
                        x = -sizeValue;
                        y = -sizeValue;
                        directionX = (float)(0.5 + rand.NextDouble() * 0.5);
                        directionY = (float)(0.5 + rand.NextDouble() * 0.5);
                        break;
                    case 5: // 右上角
                        x = screenWidth + sizeValue;
                        y = -sizeValue;
                        directionX = (float)(-1.0 - rand.NextDouble() * 0.5);
                        directionY = (float)(0.5 + rand.NextDouble() * 0.5);
                        break;
                    case 6: // 右下角
                        x = screenWidth + sizeValue;
                        y = screenHeight + sizeValue;
                        directionX = (float)(-1.0 - rand.NextDouble() * 0.5);
                        directionY = (float)(-1.0 - rand.NextDouble() * 0.5);
                        break;
                    default: // 左下角
                        x = -sizeValue;
                        y = screenHeight + sizeValue;
                        directionX = (float)(0.5 + rand.NextDouble() * 0.5);
                        directionY = (float)(-1.0 - rand.NextDouble() * 0.5);
                        break;
                }
            }
            
            // 标准化方向向量
            float length = (float)Math.Sqrt(directionX * directionX + directionY * directionY);
            directionX /= length;
            directionY /= length;
            
            // 设置陨石属性
            asteroid.X = x;
            asteroid.Y = y;
            asteroid.Width = sizeValue;
            asteroid.Height = sizeValue;
            asteroid.Size = size;
            asteroid.Speed = speed;
            
            // 设置速度
            float speedValue = SpeedValues[(int)speed];
            asteroid.VelocityX = directionX * speedValue;
            asteroid.VelocityY = directionY * speedValue;
            
            // 设置旋转速度
            asteroid.rotationSpeed = (float)(rand.NextDouble() * 2 - 1) * 2.0f;
            asteroid.rotationAngle = 0;
            
            // 标记形状需要更新
            asteroid.shapeNeedsUpdate = true;
            asteroid.IsActive = true;
        }
        
        /// <summary>
        /// 批量创建随机陨石
        /// </summary>
        /// <param name="screenWidth">屏幕宽度</param>
        /// <param name="screenHeight">屏幕高度</param>
        /// <param name="difficulty">难度系数（0-1）</param>
        /// <param name="minCount">最小生成数量</param>
        /// <param name="maxCount">最大生成数量</param>
        /// <returns>新创建的陨石列表</returns>
        public static List<Asteroid> CreateRandomAsteroids(int screenWidth, int screenHeight, float difficulty, int minCount, int maxCount)
        {
            Random rand = new Random();
            int count = rand.Next(minCount, maxCount + 1);
            List<Asteroid> asteroids = new List<Asteroid>();
            
            for (int i = 0; i < count; i++)
            {
                // 使用不同的随机种子确保陨石位置不同
                int seed = rand.Next() + i;
                asteroids.Add(CreateRandomAsteroid(screenWidth, screenHeight, difficulty, seed));
            }
            
            return asteroids;
        }
    }
} 